#include "Interpreter.h"
#include "common.h"
#include <iostream>

Interpreter::Interpreter() {
}

Interpreter::~Interpreter() {
}

void Interpreter::clearData() {
	root = NULL;
	instructionType = "";
	tableName = "";
	attr.clear();
	defaul.clear();
	primaryKey.clear();
	newRowAttr.clear();
	newRowValue.clear();
	attrList.clear();
	condition = NULL;
	selectAllAttr = 0;
}

void Interpreter::work(SyntaxTree *tr) {
	clearData();
	root = tr->getRootNode();
	if (!extractDataFromTree()) {
		std::cout << "Extract from tree error." << std::endl;
	} else {
		doActions();
	}
}

void Interpreter::doActions() {
	std::map<std::string, Table>::iterator it = tables.find(tableName);
	if (instructionType == "create" && it != tables.end()) {
		std::cout << "Error: Table '" << tableName << "' already exists."
				<< std::endl;
		return;
	} else if (instructionType != "create" && it == tables.end()) {
		std::cout << "Error: Table '" << tableName << "' has not been created."
				<< std::endl;
		return;
	}

	if (instructionType == "create") {
		createAction(tables[tableName]);
	} else if (instructionType == "insert") {
		insertAction(tables[tableName]);
	} else if (instructionType == "delete") {
		deleteAction(tables[tableName]);
	} else if (instructionType == "select") {
		selectAction(tables[tableName]);
	}
}

bool Interpreter::getAttributeList(SyntaxTreeNode *cur) {
	while (cur != NULL) {
		if (cur->getType() != COLUMN_LIST) {
			cur = cur->getLeft();
		} else {
			std::string s = cur->getRight()->getIdName();
			attrList.push_back(s);
			cur = cur->getLeft();
		}
	}
	return true;
}

bool Interpreter::searchDECL_LIST(SyntaxTreeNode *cur) {
	if (DECL == cur->getRight()->getType()) {
		SyntaxTreeNode *c = cur->getRight(); // c == DECL
		if (DEFAULT_SPEC == c->getLeft()->getType()) {
			// c->getLeft() == DEFAULT
			// c->getRight() == id name
			attr.push_back(c->getRight()->getIdName());
			defaul[c->getRight()->getIdName()] =
					c->getLeft()->getLeft()->getValue();
		} else if ("PRIMARY KEY" == c->getLeft()->getIdName()) { // primary key
				// c->getLeft() == PRIMARY
				// c->getRight() == COLUMN_LIST
			SyntaxTreeNode *t = c->getRight(); // t == COLUMN_LIST
			do {
				primaryKey.push_back(t->getRight()->getIdName());
				t = t->getLeft();
			} while (t != NULL);
		} else {
			return false;
		}
	} else {
		return false;
	}

	if (NULL != cur->getLeft() && DECL_LIST == cur->getLeft()->getType()) {
		searchDECL_LIST(cur->getLeft());
	}
	return true;
}

bool Interpreter::extractDataFromTree() {
	if (CREATE == root->getType()) {
		instructionType = "create";
		tableName = root->getLeft()->getIdName();

		if (DECL_LIST == root->getRight()->getType()) {
			if (false == searchDECL_LIST(root->getRight())) {
				return false;
			}
		} else {
			return false;
		}
	} else if (INSERT == root->getType()) {
		instructionType = "insert";
		tableName = root->getRight()->getIdName();
		SyntaxTreeNode *column_list = root->getRight()->getRight();
		SyntaxTreeNode *value_list = root->getRight()->getLeft();

		do {
			newRowAttr.push_back(column_list->getRight()->getIdName());
			column_list = column_list->getLeft();
		} while (column_list != NULL);
		do {
			newRowValue.push_back(value_list->getRight()->getValue());
			value_list = value_list->getLeft();
		} while (value_list != NULL);
	} else if (DELETE == root->getType()) {
		instructionType = "delete";
		tableName = root->getLeft()->getIdName();

		if (root->getRight() == NULL) {
			return true;
		} else {
			if (WHERE_CLAUSE == root->getRight()->getType()) {
				condition = root->getRight();
				return true;
			} else {
				return false;
			}
		}
		return false;
	} else if ("QUERY" == root->getIdName()) {
		instructionType = "select";
		tableName = root->getLeft()->getIdName();
		SyntaxTreeNode *currentNode = root->getLeft();

		if (currentNode->getRight()->getType() == MUL) {
			selectAllAttr = 1;
		} else if (currentNode->getRight()->getIdName() == "SELECT_LIST") {
			currentNode = currentNode->getRight();
			getAttributeList(currentNode);
		} else {
			return false;
		}
		currentNode = root->getLeft()->getLeft();
		if (currentNode == NULL) {
			return true;
		} else {
			if (WHERE_CLAUSE == currentNode->getType()) {
				condition = currentNode;
				return true;
			}
			return false;
		}
		return false;
	} else {
		return false;
	}
	return true;
}

void Interpreter::createAction(Table &ta) {
	int result = ta.Create(tableName, attr, defaul, primaryKey);
	if (result == 0) {
		std::cout << "Create table '" << tableName << "' succeed!\n" << std::endl;
	} else {
		std::cout << "Error in Create: ";
		if (result == 1) {
			std::cout << "# of columns over 100 " << std::endl;
		} else if (result == 2) {
			std::cout << "duplicate column names." << std::endl;
		} else if (result == 3) {
			std::cout << "primary key contains columns out of the table"
					<< std::endl;
		} else {
			std::cout << "Unknown error: " << result << std::endl;
		}
	}
}

void Interpreter::insertAction(Table &ta) {
	int result = ta.Insert(newRowAttr, newRowValue);
	if (result == 0) {
		std::cout << "Insert table '" << tableName << "' succeed!\n" << std::endl;
	} else {
		std::cout << "Error in Insert: ";
		if (result == 1) {
			std::cout << "primary key constraint violation." << std::endl;
		} else if (result == 2) {
			std::cout << "column is not in the schema of the table."
					<< std::endl;
		} else if (result == 3) {
			std::cout << "duplicate columns." << std::endl;
		} else if (result == 4) {
			std::cout << "# of columns should equal to # of values."
					<< std::endl;
		} else {
			std::cout << "Unknown error: " << result << std::endl;
		}
	}
}

void Interpreter::deleteAction(Table &ta) {
	int result = ta.Delete(condition);
	if (result == 0) {
		std::cout << "Deleted from '" << tableName <<"' successfully!\n" << std::endl;
	} else {
		std::cout << "Error in Delete: ";
		if (result == 2) {
			std::cout
					<< "columns occurring in the where clause is out of the schema of the table"
					<< std::endl;
		} else if (result == 3) {
			std::cout << "bool sentence error" << std::endl;
		} else if (result == 4) {
			std::cout << "getting equation error." << std::endl;
		} else if (result == 5) {
			std::cout
					<< "columns occurring in the where clause is out of the schema of the table"
					<< std::endl;
		} else if (result == 6) {
			std::cout << "calculate equation error." << std::endl;
        } else if (result == 7) {
            std::cout << "error, divided by zero." << std::endl;
		} else {
			std::cout << "Unknown error: " << result << std::endl;
		}
	}
}

void Interpreter::selectAction(Table &ta) {
	int result = ta.Select(attrList, condition, selectAllAttr);
	if (result == 0) {
		std::cout << "selected from '" << tableName << "' successfully!\n" << std::endl;
	} else {
		std::cout << "Error in Select: ";
		if (result == 1) {
			std::cout
					<< "columns in the select list is not in the schema of the table."
					<< std::endl;
		} else if (result == 2) {
			std::cout << "error, the attributes don't exsits in table."
					<< std::endl;
		} else if (result == 3) {
			std::cout << "bool sentence error" << std::endl;
		} else if (result == 4) {
			std::cout << "getting equation error." << std::endl;
		} else if (result == 5) {
			std::cout
					<< "columns occurring in the where clause is out of the schema of the table"
					<< std::endl;
		} else if (result == 6) {
			std::cout << "calculate equation error." << std::endl;
        } else if (result == 7) {
            std::cout << "error, divided by zero." << std::endl;
		} else {
			std::cout << "Unknown error: " << result << std::endl;
		}
	}
}
